﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using PloobsEngine.SceneControl;
using PloobsEngine.MessageSystem;
using PloobsEngine.Events;


namespace PloobsEngine.IA
{
    public class FollowState : IState
    {
        #region IState Members

        public FollowState(List<Vector3> path, bool loopInPath, IWorld world)
        {
            this.loop = loopInPath;
            this.path = path;
            this.world = world;
        }

        public FollowState(List<Waypoint> path, bool loopInPath, IWorld world)
        {
            this.world = world;
            this.loop = loopInPath;
            List<Vector3> vec = new List<Vector3>();
            foreach (Waypoint item in path)
            {
                vec.Add(item.WorldPos);
            }
            this.path = vec;
        }


        public FollowState(List<Vector3> path, IWorld world)
        {
            this.path = path;
            this.world = world;
        }
        private IWorld world;
        private bool loop = false;
        private IObject obj;
        private List<Vector3> path;
        private int currentPath = 1;
        private string nextState = null;
        private VisibilitySensor vsensor;
        FollowPathActuator actuator;

        ActuatorsResponsesSensor sensor;
        private String nextStateName = null;

        public String NextStateEndPathName
        {
            get { return nextStateName; }
            set { nextStateName = value; }
        }

        public void Init(IObject obj)
        {
            this.obj = obj;

            actuator = new FollowPathActuator(obj);
            sensor = new ActuatorsResponsesSensor();
            actuator.Attach(sensor);
            actuator.SetPath(path[0], path[1]);
            vsensor = new VisibilitySensor(world, obj);
            vsensor.DistanciaDoCentroDeMassa = 2;
            vsensor.Distance = 3;
            vsensor.Altura = 1;

        }

        public string NextState()
        {
            return nextState;
        }

        public void UpdateState()
        {
            IDictionary<String, ActuatorSensorInformation> resp = sensor.DetectEnviroment();
            IList<VisibilitySensorInformation> vinfo = vsensor.DetectEnviroment();

            if (resp.Count != 0)
            {
                if (resp[actuator.Name].Ended)
                {
                    if (path.Count == currentPath + 1)
                    {
                        if (loop)
                        {
                            actuator.SetPath(path[currentPath], path[0]);
                            currentPath = 0;
                            return;
                        }
                        else
                        {
                            nextState = NextStateEndPathName;
                            return;
                        }
                    }
                    actuator.SetPath(path[currentPath], path[++currentPath]);
                }
            }
            bool canrun = true;
            List<IObject> inter = new List<IObject>();
            if (vinfo.Count != 0)
            {
                foreach (VisibilitySensorInformation item in vinfo)
                {
                    inter.Add(item.Agente.Obj);
                    if (!knowCarStates.Contains(item.Agente.Obj.getId()))
                    {
                        Message message = new Message(this.obj.getId(), item.Agente.Obj.getId(), null, Priority.HIGH, -1, SenderType.IA, null, STOPPING);
                        MessageDeliver.SendMessageWithChecking(message);
                        canrun = false;
                    }
                    else
                    {
                    }
                }

            }
            foreach (IObject item in lastFrameDetected)
            {
                if (!inter.Contains(item))
                {
                    Message message = new Message(this.obj.getId(), item.getId(), null, Priority.HIGH, -1, SenderType.IA, null, RUN);
                    MessageDeliver.SendMessageWithChecking(message);
                }
            }
            lastFrameDetected = inter;

            if (canrun)
            {
                actuator.Actuate();
            }
            else
            {
            }

        }

        public IList<int> KnowCarStates
        {
            get { return knowCarStates; }
            set { knowCarStates = value; }
        }

        IList<int> knowCarStates = new List<int>();

        List<IObject> lastFrameDetected = new List<IObject>();
        public readonly static string STOPPING = "STOPPING";
        public readonly static string RUN = "RUN";

        public void Finish()
        {
            nextState = null;
        }

        #endregion

        #region IState Members


        public IEventHandler EventHandler
        {
            get
            {
                return null;
            }
            set
            {
                
            }
        }

        #endregion
    }
}
